package cn.ffcs.base.lang;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

/**
 * Provides a helper that locates the declarated generics type of a class.
 * 泛型类类型获取。
 * 
 * @author Daniel
 * @version $LastChangedRevision: 24 $
 */
public class GenericsUtils {
    /**
     * Locates the first generic declaration on a class.
     * 
     * @param clazz
     *            The class to introspect
     * @return the first generic declaration, or <code>null</code> if cannot
     *         be determined
     */
    public static Class<? extends Object> getGenericClass(
            Class<? extends Object> clazz) {
        return getGenericClass(clazz, 0);
    }

    /**
     * Locates generic declaration by index on a class.
     * 
     * @param clazz
     *            clazz The class to introspect
     * @param index
     *            the Index of the generic ddeclaration,start from 0.
     */
    public static Class<? extends Object> getGenericClass(
            Class<? extends Object> clazz, int index) {
        Type genType = clazz.getGenericSuperclass();

        if (genType instanceof ParameterizedType) {
            Type[] params = ((ParameterizedType)genType)
                    .getActualTypeArguments();

            if ((params != null) && (params.length >= (index - 1))) {
                return (Class<? extends Object>)params[index];
            }
        }
        return null;
    }

    /**
     * 获取默认的泛型类型名称
     * @param clazz
     * @return
     */
    public static String getGenericClassName(Class<? extends Object> clazz) {
        Class clz = GenericsUtils.getGenericClass(clazz);
        if (clz != null) {
            return clz.getName();
        }
        return null;
    }

    /**
     * 获取默认的泛型类型名称
     * @param clazz
     * @param index
     * @return
     */
    public static String getGenericClassName(Class<? extends Object> clazz,
            int index) {
        Class clz = GenericsUtils.getGenericClass(clazz, index);
        if (clz != null) {
            return clz.getName();
        }
        return null;
    }
}